Александр
да
Anonymous
Спасибо
Anonymous
Теперь имею представление как это реализовать.
Anonymous
когда клиент подключается к ws, ассоциированная с клиентом рутина начинает слушать канал уведомлений для юзера.
как только туда что-то приходит, рутина посылает это в сокет клиенту
Anonymous
Не реклама
Anonymous
Видели?
Anonymous
Alexey Troyanov:
http://xidea.online/
Anonymous
Лицензировать любой продукт jetbrains
Anonymous
Интересно с goland сработает?
Александр
Уже несколько лет назад появились такие сервера. Но лучше купить или получить бесплатно, если есть opensource-продукт
Kirill
еще студ лицухи есть)
Anonymous
Ну так goland триал только? Я вот pycharm качаю CE
Anonymous
Kirill
у jetBrains
Kirill
второй год юзаю
Александр
Года 4 назад я открывал какойто файлик в архиве eap ide и ежемесячно менял там дату)
Kirill
Anonymous
Александр
А 4 года назад вы пользовались идеей?)
Anonymous
А если просто дату на компе менять, работает?
Anonymous
Ну года 2 юзаю
Anonymous
Александр
Ну вот поэтому и не знали) Выживали как могли)
Александр
До этого эклипс был, тот еще тормоз
Anonymous
От, я тоже с эклипса на джаве начинал, жесть ещё та
Александр
На тот момент он казался офигенным)
Anonymous
😂👍
Chebyrash
Александр
Как можно архитектурно зарефакторить такой код?
switch incomeEvent.Action {
case models.CALL:
switch incomeEvent.Method {
case models.GET:
getRequestHandler(incomeEvent)
case models.POST:
postRequestHandler(incomeEvent)
}
case models.SUBSCRIBE:
switch incomeEvent.Method {
case models.POST:
postSubscribeHandler(incomeEvent)
}
}
P.S. Внутри этих методов еще switch.
Полиморфизм? Регистрация колбеков? Мб еще варианты есть? В golang новичок. Такая вложенность, еще и раскиданная по файлам мне не нравится
Попробовал сделать. Мне не нравится, много действий нужно сделать. Но сам switch стал хотя бы читаемый
type IncomingHandlerPool struct {
messages MessagesHandler
}
type MessagesHandler interface {
GetMessages(event models.IncomeEvent)
GetChatsCount(event models.IncomeEvent)
SendMessage(event models.IncomeEvent)
MarkRead(event models.IncomeEvent)
NotifyTyping(event models.IncomeEvent)
}
const (
requestMessages = "request_messages"
requestChatsCount = "request_chats_count"
sendMessage = "send_message"
markRead = "mark_read"
notifyTyping = "notify_typing"
)
var (
handlerKeys = map[string]string{
requestMessages: handleKey(models.CALL, models.GET, models.TYPE_MESSAGE),
requestChatsCount: handleKey(models.CALL, models.GET, models.TYPE_COUNTS),
sendMessage: handleKey(models.CALL, models.POST, models.TYPE_MESSAGE),
markRead: handleKey(models.CALL, models.POST, models.TYPE_READ),
notifyTyping: handleKey(models.CALL, models.POST, models.TYPE_TYPING),
}
)
// ...
switch handleKey(incomeEvent.Action, incomeEvent.Method, incomeEvent.Type) {
case requestMessages: handlers.messages.GetMessages(incomeEvent)
case requestChatsCount: handlers.messages.GetChatsCount(incomeEvent)
case sendMessage: handlers.messages.SendMessage(incomeEvent)
case markRead: handlers.messages.MarkRead(incomeEvent)
case notifyTyping: handlers.messages.NotifyTyping(incomeEvent)
}
// ...
func handleKey(a int, m string, t string) string {
return fmt.Sprintf("%s-%s-%s", a, m, t)
}
Александр
Как не потерять читаемость, но убрать эту громоздкость?)
Anonymous
Я делаю пакет app и пишу там routers handlers и models
Александр
Anonymous
В main уже просто сервак
Anonymous
Это вообще норм? Потому как мне удобно так, в стиле django
Anonymous
Александр
Вот так уже проще) По имени метода понятно, что это за кейс
type IncomingHandlers struct {
messages MessagesHandler
}
type MessagesHandler interface {
GetMessages(event models.IncomeEvent)
GetChatsCount(event models.IncomeEvent)
SendMessage(event models.IncomeEvent)
MarkRead(event models.IncomeEvent)
NotifyTyping(event models.IncomeEvent)
}
var (
handlers = IncomingHandlers{
messages: &MessagesServerHandler{},
}
)
// ...
switch handleKey(incomeEvent.Action, incomeEvent.Method, incomeEvent.Type) {
case handleKey(models.CALL, models.GET, models.TYPE_MESSAGE):
handlers.messages.GetMessages(incomeEvent)
case handleKey(models.CALL, models.GET, models.TYPE_COUNTS):
handlers.messages.GetChatsCount(incomeEvent)
case handleKey(models.CALL, models.POST, models.TYPE_MESSAGE):
handlers.messages.SendMessage(incomeEvent)
case handleKey(models.CALL, models.POST, models.TYPE_READ):
handlers.messages.MarkRead(incomeEvent)
case handleKey(models.CALL, models.POST, models.TYPE_TYPING):
handlers.messages.NotifyTyping(incomeEvent)
}
Anonymous
А интерфейс на одну сущность?
Александр
Anonymous
Аа
Александр
Anonymous
Оу
Anonymous
Зная норм
Anonymous
Просто чтобы подключить ещё приложение, создам пакет
Anonymous
Я сомневался если честн
Nikita
Nikita
если у тебя есть долгоживующий процесс и тебе надо как бы отслеживать его состояние, лучше возвращать структуру с каналами, откуда ты будешь ловить события
Nikita
и еще с мапами надо осторожно храня в глобальной переменной
Nikita
если будешь читать их с двух рутин, получишь гонку
Slach
а есть какой то быстрый способ посчитать кол-во аллокаций если у меня маленькая функция main
памяти кроме тестов
и кроме GODEBUG=allocfreetrace=1
?
Александр
Александр
Если с маленькой буквы
Anonymous
Nikita
Slach
А atomic? Не подходит?
а конкретно ???
ну вот я учу Го
хочу понять как правильно аллоцировать
написал простейший код
https://play.golang.org/p/WQVXfwWzue
хочу понять сколько в нем аллокаций
запустил GODEBUG=allocfreetrace=1 go run test.go
и получил тонну вывода... и большинство аллокаций вообще не в моем коде =(
как померить правильно?
Александр
нет у тебя гарантии, что код в твоем пакете не будет читать твою мапу из нескольких рутин
Ну, если честно, эти обработчики обрабатываются в пакете, снаружи нужно только предоставлять данные для обработчика внутри и реагировать на события асинхронно.
С реакцией на события соглашусь, можно каналы давать, но что делать, когда нужно получить данные?
Вот у меня есть GetMessages. Он делает какую-то внутренню бизнес-логику, в середине ему нужно получить сообщения от клиентского кода, из них сформировать структуру и отправить в свой канал. Тут каналы не лишнее использовать?
Александр
Anonymous
Sergey
Александр
Александр
просто дёргаю callback
Oleg
Ну, если честно, эти обработчики обрабатываются в пакете, снаружи нужно только предоставлять данные для обработчика внутри и реагировать на события асинхронно.
С реакцией на события соглашусь, можно каналы давать, но что делать, когда нужно получить данные?
Вот у меня есть GetMessages. Он делает какую-то внутренню бизнес-логику, в середине ему нужно получить сообщения от клиентского кода, из них сформировать структуру и отправить в свой канал. Тут каналы не лишнее использовать?
памятую , давно кто-то мне говорил, если ты задумываешься о том использовать каналы или нет, то их не надо использовать.
Oleg
я думаю, пока забудьте о них на время, разве-что поробуйте и всё. Там есть что учить, а потом на уровне стандартных пакетов разберётесь как и когда их применять. Как говориться, это ты должен сердцем чуять, когда их применять а когда нет. Усложнить и хелловорлд можно , но зачем? Но эт только моё мнение, у каждого свой путь.)
Александр
Ну, в сервере для чатов сложно о них забыть) Хочешь-не хочешь, а для внутренней работы сервера они 100% нужны
Nikita
Ну, если честно, эти обработчики обрабатываются в пакете, снаружи нужно только предоставлять данные для обработчика внутри и реагировать на события асинхронно.
С реакцией на события соглашусь, можно каналы давать, но что делать, когда нужно получить данные?
Вот у меня есть GetMessages. Он делает какую-то внутренню бизнес-логику, в середине ему нужно получить сообщения от клиентского кода, из них сформировать структуру и отправить в свой канал. Тут каналы не лишнее использовать?
Если тебе совсем надо заинкапсулировать обработчик канала, чтобы, например, не дать его закрыть, можешь создать интерфейс, где будешь отдавать канал только на чтение. Надо максимально пытаться избегать коллбек-лапши а-ля жаваскрипт
Nikita
Нет
До го 1.6 чтение из мап было при любых обстоятельства нормально, сейчас же, если в мапу происходит запись, чтение из нее вызовет панику
Александр
Если тебе совсем надо заинкапсулировать обработчик канала, чтобы, например, не дать его закрыть, можешь создать интерфейс, где будешь отдавать канал только на чтение. Надо максимально пытаться избегать коллбек-лапши а-ля жаваскрипт
В том и прикол, что клиент должен записать туда данные, а не читать, если это будет канал, причём либо синхронно, либо wg какой-нибудь
func (c *MessagesServerHandler) GetMessages(event models.IncomeEvent) {
response, err := client.GetChatMessages(event)
if err != nil {
resultChan <- event.CreateResult(nil, err.Error())
return
}
resultChan <- event.CreateResult(response, nil)
}
Nikita
Не стоит пихать все результаты в один канал, создай два
Nikita
В один канал ошибки, в другой - удачный результат
Александр
+ нужно его уведомить, что сейчас нужно туда записать
Nikita
какая-то лапша. Можешь описать логику, что за сообщения и с кем ты там обмениваешься?
Александр
В сокеты прилетает что-то типа json-rpc - например, запрашивают список сообщений.
Сервер должен распарсить запрос, понять, что хочет браузер, и отдать этот список сообщений опять же в определенном формате типа json-rpc
Сами сообщения сервер не хранит, и к базе доступа нет, поэтому нужно это сделать другому (клиентскому) коду, но этот код не должен влиять на сам протокол работы сервера.
У нас несколько проектов, и эти чаты нужны оказались на еще одном проекте. Не хочется с нуля писать сервер и разрабатывать свой протокол обмена с браузером, поэтому то, что реализует протокол, решили выделить в отдельный пакет, а всё взаимодействие с конкретным проектом - это должно быть реализовано уже в конкретном проекте
Александр
Клиенты для ios/android/js есть, их можно переиспользовать, только если протокол не изменится
Chebyrash
Друзья, насколько "костыльно" использовать build тэги с сорцах? В доках на эту тему целая страница, но в коде на гитхабе такое редко встречаются..